package cn.shengchao.order.user;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.shengchao.cap.acl.ports.repositories.IProductThirdCapOrderGradeRepository;
import cn.shengchao.examstar.gankao.acl.ports.repositories.IGanKaoRepository;
import cn.shengchao.examstar.product.acl.ports.repositories.IProductUserOrderAfterLogRepository;
import cn.shengchao.examstar.product.acl.ports.repositories.IProductUserOrderExpiredRepository;
import cn.shengchao.examstar.rpc.gankao.GanKaoOrderGoodsListDto;
import cn.shengchao.examstar.rpc.orders.res.PayOrderInfoDto;
import cn.shengchao.examstar.rpc.orders.res.PayOrderItemInfoDto;
import cn.shengchao.examstar.rpc.product.base.*;
import cn.shengchao.examstart.user.acl.adapters.repositories.UserRepository;
import cn.shengchao.examstart.user.domain.entity.User;
import cn.shengchao.ycbdc.acl.ports.repositories.IProductThirdYcbdcUserOrderRepository;
import cn.shengchao.ycbdc.domain.result.UserInfoResult;
import cn.shengchao.ycbdc.domain.token.YcBdcTokenUtil;
import cn.shengchao.ycbdc.infrastructure.dao.po.ProductThirdYcbdcUserOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @program: examstarapi
 * @description: 用户支付订单后的产品有效期统一处理
 * @author: Xiong weiqiang
 * @create: 2025-06-27 20:37
 */
@Component
public class UserOrderProductExpiredProcessor {
    @Autowired
    UserRepository userRepository;

    @Autowired
    YcBdcTokenUtil ycBdcTokenUtil;

    @Autowired
    private IProductThirdCapOrderGradeRepository orderGradeRepository;
    @Autowired
    private IProductThirdYcbdcUserOrderRepository ycbdcUserOrderRepository;
    @Autowired
    private IProductUserOrderExpiredRepository productUserOrderExpiredRepository;
    @Autowired
    private IGanKaoRepository ganKaoRepository;
    @Autowired
    IProductUserOrderAfterLogRepository productUserOrderAfterLogRepository;
    /**
     * 根据用户订单信息处理产品有效期
     * @param productPropertyDtoMap
     * @param payOrderInfoDto
     */
    @Transactional
    public void processUserProductAfterPay(Map<Long,ProductPropertyDto> productPropertyDtoMap, PayOrderInfoDto payOrderInfoDto) {
        String userId=payOrderInfoDto.getUserId();
        User user=userRepository.of(Long.parseLong(userId));
        String orderId=payOrderInfoDto.getOrderId();
        String productId=payOrderInfoDto.getProductId();
        if (user==null){
            //用户不存在，错误
            productUserOrderAfterLogRepository.logError(userId,payOrderInfoDto,null,"本地用户加载失败");
        }
        //没子订单的第三方产品，按主订单处理。
        if (CollUtil.isEmpty(payOrderInfoDto.getOrderItemInfos())){
            ProductPropertyDto productPropertyDto=productPropertyDtoMap.get(Long.parseLong(productId));
            processUserProductSingleProductAfterPay(productPropertyDto,payOrderInfoDto,null);
        }else{
            List<GanKaoOrderGoodsListDto> goodsList=new ArrayList<>();
            GanKaoOrderGoodsListDto ganKaoOrderGoodsListDto=new GanKaoOrderGoodsListDto();
            Map<String, BigDecimal> productPriceMap=payOrderInfoDto.getOrderItemInfos().stream().collect(Collectors.toMap(PayOrderItemInfoDto::getProductId,PayOrderItemInfoDto::getTotalAmount));
            BigDecimal ganKaoProductTotal=BigDecimal.ZERO;
            for (ProductPropertyDto productPropertyDto:productPropertyDtoMap.values()){
                if (productPropertyDto.getCourseProductSettingDto().getProductType().equals(ContentProductTypeDefine.COURSE_GK.name())){
                    BigDecimal price=productPriceMap.get(productPropertyDto.getCourseProductSettingDto().getProductId().toString());
                    ganKaoOrderGoodsListDto.setSectionId(Integer.valueOf(productPropertyDto.getCourseProductSettingDto().getRefThirdId()));
                    ganKaoOrderGoodsListDto.setExpiredDays(productPropertyDto.getCourseProductSettingDto().getUnitPayDay());
                    ganKaoOrderGoodsListDto.setPrice(price);
                    //单独累加赶考课程价格
                    ganKaoProductTotal=ganKaoProductTotal.add( price);
                    goodsList.add(ganKaoOrderGoodsListDto);
                }
            }
            if (!goodsList.isEmpty()){
                //如果非空得给赶考提交数据
                boolean orderSync=  ganKaoRepository.checkOrderCourseAndSync(orderId,payOrderInfoDto.getOrderTime(),ganKaoProductTotal,user.getId(),goodsList);
                if(!orderSync){
                    productUserOrderAfterLogRepository.logError(userId,payOrderInfoDto,null,"赶考订单产品处理失败："+ JSONUtil.toJsonStr(goodsList));
                }
            }
            //课程订单，聚合订单
            List<CompletableFuture<Void>> futures=new ArrayList<>();
            payOrderInfoDto.getOrderItemInfos().forEach(orderItemInfo -> {
                ProductPropertyDto productPropertyDto=productPropertyDtoMap.get(Long.parseLong(orderItemInfo.getProductId()));
                futures.add(CompletableFuture.runAsync(() -> {
                    processUserProductSingleProductAfterPay(productPropertyDto,payOrderInfoDto,orderItemInfo);
                }).exceptionally(e->{
                    productUserOrderAfterLogRepository.logError(userId,payOrderInfoDto,orderItemInfo,"子订单产品处理失败："+e.getMessage());
                    return null;
                }));
            });
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        }
    }

    /**
     * 单个产品再分处理。
     * @param productPropertyDto
     * @param payOrderInfoDto
     * @param payOrderItemInfoDto
     */
    public void processUserProductSingleProductAfterPay(ProductPropertyDto productPropertyDto, PayOrderInfoDto payOrderInfoDto, PayOrderItemInfoDto payOrderItemInfoDto){
        String userId=payOrderInfoDto.getUserId();
        String orderId=payOrderInfoDto.getOrderId();
        User user=userRepository.of(Long.parseLong(userId));
        String productId=payOrderInfoDto.getProductId();
        if (productPropertyDto==null){
            productUserOrderAfterLogRepository.logError(user.getId(),orderId,payOrderInfoDto.getOrderTime(),productPropertyDto,false,"产品属性加载失败");
        }
        //高考志愿CAP,忆成背单词YCBCD,没有子订单
       if (productPropertyDto.getProductType().equals(ContentProductTypeDefine.PRODUCT_THIRD_YCBDC.name())){
           ycbdcOrderProductAfterPay(productPropertyDto, user, orderId, payOrderInfoDto.getOrderTime(), productId);
        }else if (productPropertyDto.getProductType().equals(ContentProductTypeDefine.PRODUCT_THIRD_CAP.name())){
          capOrderProductAfterPay(productPropertyDto, user, orderId, payOrderInfoDto.getOrderTime(), productId);
        }else {
           //获取子订单的产品属性
           ProductSettingDto productSettingDto =productPropertyDto.getCourseProductSettingDto();
           if (productSettingDto.getProductType().equals(ContentProductTypeDefine.COURSE_GK.name())){
                //赶考课程
               gkCourseOrderProductAfterPay(productPropertyDto, user, orderId, payOrderInfoDto.getOrderTime());
           }else if (productSettingDto.getProductType().equals(ContentProductTypeDefine.COURSE.name())){
               //本地课程
               localCourseOrderProductAfterPay(productPropertyDto, user, orderId, payOrderInfoDto.getOrderTime());
           }else {
               productUserOrderAfterLogRepository.logError(userId,payOrderInfoDto,payOrderItemInfoDto,"不支持的产品订单：无子订单");
           }
       }
    }

    /**
     * 忆成背单词是按买的产品定的有效期
     * @param productPropertyDto
     * @param user
     * @param orderId
     * @param orderTime
     * @param productId
     */
    private void ycbdcOrderProductAfterPay(ProductPropertyDto productPropertyDto, User user, String orderId,Date orderTime,String productId) {
        //获取绑定的随机手机号
        String phone=ycbdcUserOrderRepository.getPhoneForUserId(user.getId());
        System.out.println("忆成英语订单服务请求交互，,user="+phone);
        ProductThirdYcbdcUserOrder ycbdcUserOrder = new ProductThirdYcbdcUserOrder();
        ycbdcUserOrder.setOrderId(orderId);
        ycbdcUserOrder.setUserId(user.getId());
        ycbdcUserOrder.setMobile(phone);
        ycbdcUserOrder.setDataStatus(1);
        int days=0;
        try {

            if (ContentProductCs.PRODUCT_ID_YCBDC_MONTH.equals(productId)){
                days=30;
            }else if (ContentProductCs.PRODUCT_ID_YCBDC_SEASON.equals(productId)){
                days=90;
            }else if (ContentProductCs.PRODUCT_ID_YCBDC_YEAR.equals(productId)){
                days=365;
            }else if (ContentProductCs.PRODUCT_ID_YCBDC_LONG.equals(productId)){
                days=36525;
            }
            boolean result=ycBdcTokenUtil.addOrderDays(phone,user.getName(),days);
            UserInfoResult userInfoResult=ycBdcTokenUtil.getUserInfo(phone,user.getName());
            ycbdcUserOrder.setExpirationDate(userInfoResult.getExpirationDate());
            ycbdcUserOrder.setSyncStatus(result?1:0);
        } catch (Exception e) {
            ycbdcUserOrder.setSyncStatus(0);
            ycbdcUserOrder.setSyncMsg(e.getMessage());
            productUserOrderAfterLogRepository.logError(user.getId(),orderId,orderTime,productPropertyDto,false,"异常产品交互失败："+e.getMessage());
        }
        ycbdcUserOrderRepository.newOrder(ycbdcUserOrder);
        ProductUserOrderExpiredDto productUserOrderExpiredDto = ProductUserOrderExpiredDto.builder()
                .orderId(orderId) .orderTime(orderTime)
                .userId(user.getId())
                .productName(productPropertyDto.getProductName())
                .productId(Long.parseLong(productId))
                .productType(productPropertyDto.getProductType())
                .expiredDay(ycbdcUserOrder.getExpirationDate())
                .buyDayNum(days)
                .build();
        productUserOrderExpiredRepository.saveOrderProductExpired(productUserOrderExpiredDto);
    }

    /**
     * 高考志愿产品后续有效期处理：记录订单年级的8月31日有效期
     * @param productPropertyDto
     * @param user
     * @param orderId
     * @param orderTime
     * @param productId
     */
    private void capOrderProductAfterPay(ProductPropertyDto productPropertyDto, User user, String orderId,Date orderTime,String productId) {
        System.out.println("高考志愿订单服务请求交互，,user="+user.getPhone());
        Integer gradeYear=orderGradeRepository.syncToThird(orderId,user.getId(),user.getPhone());
        if (gradeYear==-1){
            productUserOrderAfterLogRepository.logError(user.getId(),orderId,orderTime,productPropertyDto,false,"同步高考志愿产品失败：无订单年级");
            return;
        }
        Date expirationDate= DateUtil.parseDate(gradeYear.toString()+"-08-31");
        ProductUserOrderExpiredDto productUserOrderExpiredDto = ProductUserOrderExpiredDto.builder()
                .orderId(orderId) .orderTime(orderTime)
                .userId(user.getId())
                .productName(productPropertyDto.getProductName())
                .productId(Long.parseLong(productId))
                .productType(productPropertyDto.getProductType())
                .expiredDay(expirationDate)
                .buyDayNum(0)
                .build();
        productUserOrderExpiredRepository.saveOrderProductExpired(productUserOrderExpiredDto);
    }

    /**
     * 本地课程订单支付成功处理课程有效期（默认两年）
     * @param productPropertyDto
     * @param user
     * @param orderId
     * @param orderTime
     */
    private void localCourseOrderProductAfterPay(ProductPropertyDto productPropertyDto, User user, String orderId,Date orderTime) {
        //本地的课程
        productUserOrderExpiredRepository.recalSaveCourseExpired(user.getId(),productPropertyDto,orderId, orderTime);

    }

    /**
     * gk课程订单支付成功处理课程有效期（正常按配置1年）
     * @param productPropertyDto
     * @param user
     * @param orderId
     * @param orderTime
     */
    private void gkCourseOrderProductAfterPay(ProductPropertyDto productPropertyDto, User user, String orderId,Date orderTime) {
        //赶考的课程，因为交互得批量，所以暂时和本地课程一样处理
        productUserOrderExpiredRepository.recalSaveCourseExpired(user.getId(),productPropertyDto,orderId, orderTime);
        ganKaoRepository.loadAndRefreshUserCourseExpired(user.getId());
    }
}